home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrecord-1.8.1 / lib / fconv.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-21  |  5.1 KB  |  252 lines

  1. /* @(#)fconv.c    1.27 00/04/21 Copyright 1985 J. Schilling */
  2. /*
  3.  *    Convert floating point numbers to strings for format.c
  4.  *    Should rather use the MT-safe routines [efg]convert()
  5.  *
  6.  *    Copyright (c) 1985 J. Schilling
  7.  */
  8. /*
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2, or (at your option)
  12.  * any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; see the file COPYING.  If not, write to
  21.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. #include <mconfig.h>    /* <- may define NO_FLOATINGPOINT */
  25. #ifndef    NO_FLOATINGPOINT
  26.  
  27. #include <stdxlib.h>
  28. #include <standard.h>
  29. #include <strdefs.h>
  30.  
  31. #if    !defined(HAVE_STDLIB_H) || defined(HAVE_DTOA)
  32. extern    char    *ecvt __PR((double, int, int *, int *));
  33. extern    char    *fcvt __PR((double, int, int *, int *));
  34. #endif
  35.  
  36. #if    defined(HAVE_ISNAN) && defined(HAVE_ISINF)
  37. #define    FOUND_ISXX
  38. #endif
  39.  
  40. #include <math.h>
  41.  
  42. #if    defined(HAVE_IEEEFP_H) && !defined(FOUND_ISXX)
  43. /*
  44.  * SVR4
  45.  */
  46. #include <ieeefp.h>
  47. #define    isnan    isnand
  48. #define    isinf    !finite
  49. #define    FOUND_ISXX
  50. #endif
  51.  
  52. #if    defined(HAVE_FP_H)  && !defined(FOUND_ISXX)
  53. /*
  54.  * WAS:
  55.  * #if    defined(__osf__) || defined(_IBMR2) || defined(_AIX)
  56.  */
  57. #include <fp.h> 
  58. #ifndef    isnan
  59. #define    isnan    IS_NAN
  60. #endif
  61. #ifndef    isinf
  62. #define    isinf    !FINITE
  63. /*#define    isinf    IS_INF*/
  64. #endif
  65. #define    FOUND_ISXX
  66. #endif 
  67.  
  68. /*
  69.  * WAS:
  70.  * #if    defined(__hpux) || defined(VMS) || defined(_SCO_DS) || defined(__QNX__)
  71.  */
  72. #if    defined(__hpux)
  73. #undef    isnan
  74. #undef    isinf
  75. #endif
  76.  
  77. #if    !defined(isnan) && !defined(HAVE_ISNAN)
  78. #define    isnan(val)    (0)
  79. #endif
  80. #if    !defined(isinf) && !defined(HAVE_ISINF)
  81. #define    isinf(val)    (0)
  82. #endif
  83.  
  84. #if !defined(HAVE_ECVT) || !defined(HAVE_FCVT) || !defined(HAVE_GCVT)
  85. #include "cvt.c"
  86. #endif
  87.  
  88. static    char    _nan[] = "(NaN)";
  89. static    char    _inf[] = "(Infinity)";
  90.  
  91. static    int    _ferr __PR((char *, double));
  92.  
  93. #ifdef    abs
  94. #    undef    abs
  95. #endif
  96. #define    abs(i)    ((i) < 0 ? -(i) : (i))
  97.  
  98. EXPORT int
  99. ftoes(s, val, fieldwidth, ndigits)
  100.     register    char     *s;
  101.             double    val;
  102.     register    int    fieldwidth;
  103.     register    int    ndigits;
  104. {
  105.     register    char    *b;
  106.     register    char    *rs;
  107.     register    int    len;
  108.     register    int    rdecpt;
  109.             int     decpt;
  110.             int    sign;
  111.  
  112.     if ((len = _ferr(s, val)) > 0)
  113.         return len;
  114.     rs = s;
  115. #ifdef    V7_FLOATSTYLE
  116.     b = ecvt(val, ndigits, &decpt, &sign);
  117.     rdecpt = decpt;
  118. #else
  119.     b = ecvt(val, ndigits+1, &decpt, &sign);
  120.     rdecpt = decpt-1;
  121. #endif
  122.     len = ndigits + 6;            /* Punkt e +/- nnn */
  123.     if (sign)
  124.         len++;
  125.     if (fieldwidth > len)
  126.         while (fieldwidth-- > len)
  127.             *rs++ = ' ';
  128.     if (sign)
  129.         *rs++ = '-';
  130. #ifndef    V7_FLOATSTYLE
  131.     if (*b)
  132.         *rs++ = *b++;
  133. #endif
  134.     *rs++ = '.';
  135.     while (*b && ndigits-- > 0)
  136.         *rs++ = *b++;
  137.     *rs++ = 'e';
  138.     *rs++ = rdecpt >= 0 ? '+' : '-';
  139.     rdecpt = abs(rdecpt);
  140. #ifndef    V7_FLOATSTYLE
  141.     if (rdecpt >= 100)
  142. #endif
  143.     {
  144.         *rs++ = rdecpt / 100 + '0';
  145.         rdecpt %= 100;
  146.     }
  147.     *rs++ = rdecpt / 10 + '0';
  148.     *rs++ = rdecpt % 10 + '0';
  149.     *rs = '\0';
  150.     return rs - s;
  151. }
  152.  
  153. /*
  154.  * fcvt() from Cygwin32 is buggy.
  155.  */
  156. #if    !defined(HAVE_FCVT) && defined(HAVE_ECVT)
  157. #define    USE_ECVT
  158. #endif
  159.  
  160. EXPORT int
  161. ftofs(s, val, fieldwidth, ndigits)
  162.     register    char     *s;
  163.             double    val;
  164.     register    int    fieldwidth;
  165.     register    int    ndigits;
  166. {
  167.     register    char    *b;
  168.     register    char    *rs;
  169.     register    int    len;
  170.     register    int    rdecpt;
  171.             int     decpt;
  172.             int    sign;
  173.  
  174.     if ((len = _ferr(s, val)) > 0)
  175.         return len;
  176.     rs = s;
  177. #ifdef    USE_ECVT
  178.     /*
  179.      * Needed on systems with broken fcvt() implementation
  180.      * (e.g. Cygwin32)
  181.      */
  182.     b = ecvt(val, ndigits, &decpt, &sign);
  183.     /*
  184.      * The next call is needed to force higher precision.
  185.      */
  186.     if (decpt > 0)
  187.         b = ecvt(val, ndigits+decpt, &decpt, &sign);
  188. #else
  189.     b = fcvt(val, ndigits, &decpt, &sign);
  190. #endif
  191.     rdecpt = decpt;
  192.     len = rdecpt + ndigits + 1;
  193.     if (rdecpt < 0)
  194.         len -= rdecpt;
  195.     if (sign)
  196.         len++;
  197.     if (fieldwidth > len)
  198.         while (fieldwidth-- > len)
  199.             *rs++ = ' ';
  200.     if (sign)
  201.         *rs++ = '-';
  202.     if (rdecpt > 0) {
  203.         len = rdecpt;
  204.         while (*b && len-- > 0)
  205.             *rs++ = *b++;
  206. #ifdef    USE_ECVT
  207.         while (len-- > 0)
  208.             *rs++ = '0';
  209. #endif
  210.     }
  211. #ifndef    V7_FLOATSTYLE
  212.     else {
  213.         *rs++ = '0';
  214.     }
  215. #endif
  216.     *rs++ = '.';
  217.     if (rdecpt < 0) {
  218.         len = rdecpt;
  219.         while (len++ < 0 && ndigits-- > 0)
  220.             *rs++ = '0';
  221.     }
  222.     while (*b && ndigits-- > 0)
  223.         *rs++ = *b++;
  224. #ifdef    USE_ECVT
  225.     while (ndigits-- > 0)
  226.         *rs++ = '0';
  227. #endif
  228.     *rs = '\0';
  229.     return rs - s;
  230. }
  231.  
  232. LOCAL int
  233. _ferr(s, val)
  234.     char    *s;
  235.     double    val;
  236. {
  237.     if (isnan(val)){
  238.         strcpy(s, _nan);
  239.         return (sizeof (_nan) - 1);
  240.     }
  241.  
  242.     /*
  243.      * Check first for NaN because finite() will return 1 on Nan too.
  244.      */
  245.     if (isinf(val)){
  246.         strcpy(s, _inf);
  247.         return (sizeof (_inf) - 1);
  248.     }
  249.     return 0;
  250. }
  251. #endif    /* NO_FLOATINGPOINT */
  252.